local CopyL = require("copy.CopyL")
local CopyDefine = require("copy.Define")
local ObjHuman = require("core.ObjHuman")
local ExcelMap = require("excel.Map")
local FamilyWarConfig = require("excel.FamilyWar")
local Timer = require("core.Timer")
local Map = require("core.Map")
local Msg = require("core.Msg")
local Obj = require("core.Obj")
local Lang = require("common.Lang")
local MapScan = require("core.MapScan")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local Grid = require("bag.Grid")
local Util = require("common.Util")
local RoleHandler = require("role.HandlerL")
local Broadcast = require("broadcast.Broadcast")
local HtmlUtil = require("common.HtmlUtil")
local MailLogicFL = require("mail.MailLogicFL")
local SceneEvent = require("core.SceneEvent")
local Config = require("Config")
local CopyConfig = ExcelMap.copy
local FamilyWarBaseConfig = FamilyWarConfig.Base[1]
local FamilyWarIncomeConfig = FamilyWarConfig.Income[1]
local InnerDataManagerFL = require("innerdata.InnerDataManagerFL")
local InnerDataDefine = require("innerdata.Define")
local ExcelMonsterConf = require("excel.Monster")
local ObjMonster = require("core.ObjMonster")

----------------------------
----------------------------
--V1 军备值
----------------------------
----------------------------

local NONE_SIDE = 0                 --暂无分队
local RED_SIDE = 1                  --红队
local BLUE_SIDE = 2                 --蓝队

FamilyWarActData = FamilyWarActData or {}

FAMILYWAR_STATUS_LEAVED = -1        --离开战场
FAMILYWAR_STATUS_NORMAL = 0         --正常状态
FAMILYWAR_STATUS_DIE = 1            --已经死亡

PKData = PKData or {}
HumanWarDataList = HumanWarDataList or {}
SideHumanIDList = SideHumanIDList or {}
StatusList = StatusList or {}
KillList = KillList or {}
HeartBeatCount = HeartBeatCount or {}
FamilyUuidSide = FamilyUuidSide or {}
OrderData = OrderData or {}
FamilyWarEndTime = FamilyWarEndTime or 0

function checkEnter(human)
    if not Config.IS_MIDDLE then
        if not human.familyUuid or human.familyUuid == "" then
            return
        end
    end
    return true
end

function onGetHumanSide(humanUuid)
    local nRoomID = CopyL.copyHuman2Room[humanUuid]
    if nRoomID and nRoomID > 0 and SideHumanIDList[nRoomID] then
        if SideHumanIDList[nRoomID][RED_SIDE][humanUuid] then
            return RED_SIDE
        elseif SideHumanIDList[nRoomID][BLUE_SIDE][humanUuid] then
            return BLUE_SIDE
        end
    end
    return NONE_SIDE
end

function onGetHumanSideByFamilyUuid(roomID, familyUuid)
    if FamilyUuidSide[roomID] and FamilyUuidSide[roomID][familyUuid] then
        return FamilyUuidSide[roomID][familyUuid].side
    end
    return NONE_SIDE
end

function onGetHumanStatus(humanUuid, roomID)
    return HumanWarDataList[roomID]._humanDataList[humanUuid] and HumanWarDataList[roomID]._humanDataList[humanUuid].status or FAMILYWAR_STATUS_LEAVED
end

function onFamilyWarRoomBegin(copyID, roomID)
    if not Config.IS_MIDDLE then
        print("room begin")
        FamilyWarEndTime = os.time() + 1200
        FamilyUuidSide[roomID] = {}
        StatusList[roomID] = {}
        local nSide = onGetRandomSide()
        for i = 1, 2 do
            StatusList[roomID][nSide] = {}

            for k, v in pairs(FamilyWarBaseConfig.monster3Data) do
                local nMonsterSide = ObjMonster.getMonsterCamps(k) 
                if nMonsterSide == nSide then
                    StatusList[roomID][nSide][k] = {BloodPre = 100, count = 0}
                end
            end
            StatusList[roomID][nSide][0] = {count = 0}
            nSide = (nSide == RED_SIDE and BLUE_SIDE or RED_SIDE)
        end

        HumanWarDataList[roomID] = {}
        HumanWarDataList[roomID]._roomData = {redScore = FamilyWarBaseConfig.redV1, blueScore = FamilyWarBaseConfig.blueV1}
        HumanWarDataList[roomID]._humanDataList = {}
        --HumanWarDataList[roomID].static = -1    -- -1 备战状态 0 战斗状态 1 结束状态

        SideHumanIDList[roomID] = {}
        SideHumanIDList[roomID][RED_SIDE] = {}
        SideHumanIDList[roomID][BLUE_SIDE] = {}

        PKData[roomID] = {curLen = FamilyWarBaseConfig.pkLen / 2, occupySide = 0}
        KillList[roomID] = {}
        OrderData[roomID] = {}
        HeartBeatCount[roomID] = 0
    end
end

--得到开始时间
function getActTime()
    local nActData = getActData()
    if not nActData then
        return 0, 0
    end
    return nActData.startTime, nActData.endTime
end

--得到活动剩余时间
function getLeftTime()
    if Config.IS_MIDDLE then
        local nActData = getActData()
        if not nActData then
            return 0
        end
        local t =  nActData.endTime - os.time()
        if t < 0 then
            t = 0
        end
        return t
    end
    return FamilyWarEndTime - os.time() 
end

function getActData()
    return FamilyWarActData
end

--开始副本
--function onFamilyWarHumanBeginCopy(human, copyID, roomID)
--
--end

function onFamilyWarHumanEndCopy(human, copyID, roomID)
    onHumanCtl(human, roomID, copyID)
end

function onInitSide(copyID, roomID, familyUuid)
    return onGetHumanSideByFamilyUuid(roomID, familyUuid)
end

function onFamilyWarHumanEnterCopy(human, copyID, roomID)
    local nSide = NONE_SIDE
    if not HumanWarDataList[roomID]._humanDataList[human._id] then
        HumanWarDataList[roomID]._humanDataList[human._id] = {status = JZWAR_STATUS_NORMAL}
        if Config.IS_MIDDLE then
            nSide = onInitSide(copyID, roomID, human.familyUuidM)
        else
            local nLen = 0
            local nFirst = ""
            for k, v in pairs(FamilyUuidSide[roomID]) do
                nLen = nLen + 1
                if nLen == 1 then
                    nFirst = k
                end
            end
            if nLen >= 2 then
                return
            elseif nLen == 0 then
                FamilyUuidSide[roomID][human.familyUuid] = {}
                FamilyUuidSide[roomID][human.familyUuid].side = BLUE_SIDE
                FamilyUuidSide[roomID][human.familyUuid].familyName = human.familyName 
                FamilyUuidSide[roomID][human.familyUuid].zhandouli = 0 
            elseif nLen == 1 and not FamilyUuidSide[roomID][human.familyUuid] then
                FamilyUuidSide[roomID][human.familyUuid] = {}
                local nFirstSide = FamilyUuidSide[roomID][nFirst].side
                print(nFirstSide)
                FamilyUuidSide[roomID][human.familyUuid].familyName = human.familyName 
                FamilyUuidSide[roomID][human.familyUuid].zhandouli = 0 
                FamilyUuidSide[roomID][human.familyUuid].side = (nFirstSide == BLUE_SIDE and RED_SIDE or BLUE_SIDE)
            end
            --Util.printTable(FamilyUuidSide)
            nSide = onInitSide(copyID, roomID, human.familyUuid)
        end
        if nSide > 0 then
            SideHumanIDList[roomID][nSide][human._id] = human
            onJumpBackPos(human)
            human.enterCopyTime = Timer.now
        end
    else
        nSide = onGetHumanSide(human._id)
        if nSide == NONE_SIDE then
            if Config.IS_MIDDLE then
                nSide = onInitSide(copyID, roomID, human.familyUuidM)
            else
                if not FamilyUuidSide[roomID][human.familyUuid] then
                    FamilyUuidSide[roomID][human.familyUuid] = {}
                    FamilyUuidSide[roomID][human.familyUuid].side = BLUE_SIDE
                    FamilyUuidSide[roomID][human.familyUuid].familyName = human.familyName 
                    FamilyUuidSide[roomID][human.familyUuid].zhandouli = 0 
                else
                    FamilyUuidSide[roomID][human.familyUuid] = {}
                    FamilyUuidSide[roomID][human.familyUuid].side = RED_SIDE 
                    FamilyUuidSide[roomID][human.familyUuid].familyName = human.familyName 
                    FamilyUuidSide[roomID][human.familyUuid].zhandouli = 0 
                end
                nSide = onInitSide(copyID, roomID, human.familyUuid)
            end
            SideHumanIDList[roomID][nSide][human._id] = human
            onJumpBackPos(human)
        else
            if nSide == BLUE_SIDE then
                human.camps = Obj.CAMPS_GOOD
            elseif nSide == RED_SIDE then
                human.camps = Obj.CAMPS_BAD
            end
        end
    end

    SideHumanIDList[roomID][nSide][human._id] = human
    HumanWarDataList[roomID]._humanDataList[human._id].status = FAMILYWAR_STATUS_NORMAL
    human.enterCopyTime = Timer.now
    onSendConfigData(human, copyID, roomID)
    onSendOrderData(human, roomID)
end

local function get_grid(itemID, itemNum, itemColor)
    local grid = Grid.create(nil, itemID, itemNum, nil, ItemDefine.qualityOut[itemColor])
    return grid
end

function onSendConfigData(human, copyID, roomID)
    local nSendMsg = Msg.gc.GC_FAMILYWAR_CONFIGDATA
    nSendMsg.pkLen = FamilyWarBaseConfig.pkLen
    nSendMsg.redLen = FamilyWarBaseConfig.redLen
    nSendMsg.blueLen = FamilyWarBaseConfig.blueLen
    nSendMsg.preLen = FamilyWarBaseConfig.pkDiff
    nSendMsg.centerRectList[0] = 0
    nSendMsg.blueBloodRectList[0] = 0
    nSendMsg.redBloodRectList[0] = 0
    nSendMsg.side = onGetHumanSide(human._id)
    nSendMsg.backBloodPre = FamilyWarBaseConfig.backBloodPre
    nSendMsg.backBloodMoney = FamilyWarBaseConfig.backBloodMoney

    nSendMsg.side = onGetHumanSide(human._id)

    --得到中心区域矩形列表
    local nCopyConfig = CopyConfig[copyID]
    local nMapID = nCopyConfig.mapList[1]
    if nMapID and nMapID > 0 then
        local nCenterAreaID = FamilyWarBaseConfig.centerAreaID
        for k, v in ipairs(nCenterAreaID) do
            local nListRect = Map.getRects(nMapID, v)
            for i = 1, #nListRect do
                nSendMsg.centerRectList[0] = nSendMsg.centerRectList[0] + 1
                local nRectMsgData = nSendMsg.centerRectList[nSendMsg.centerRectList[0]]
                local nRect = nListRect[i]
                nRectMsgData.leftTopPosX = nRect[1]
                nRectMsgData.leftTopPosY = nRect[2]
                nRectMsgData.rightBottomPosX = nRect[3]
                nRectMsgData.rightBottomPosY = nRect[4]
            end
        end

        local nRedBackBloodAreaID = FamilyWarBaseConfig.redBackBloodAreaID
        for k, v in ipairs(nRedBackBloodAreaID) do
            local nListRect = Map.getRects(nMapID, v)
            for i = 1, #nListRect do
                nSendMsg.redBloodRectList[0] = nSendMsg.redBloodRectList[0] + 1
                local nRectMsgData = nSendMsg.redBloodRectList[nSendMsg.redBloodRectList[0]]
                local nRect = nListRect[i]
                nRectMsgData.leftTopPosX = nRect[1]
                nRectMsgData.leftTopPosY = nRect[2]
                nRectMsgData.rightBottomPosX = nRect[3]
                nRectMsgData.rightBottomPosY = nRect[4]
            end
        end

        local nBlueBackBloodAreaID = FamilyWarBaseConfig.blueBackBloodAreaID
        for k, v in ipairs(nBlueBackBloodAreaID) do
            local nListRect = Map.getRects(nMapID, v)
            for i = 1, #nListRect do
                nSendMsg.blueBloodRectList[0] = nSendMsg.blueBloodRectList[0] + 1
                local nRectMsgData = nSendMsg.blueBloodRectList[nSendMsg.blueBloodRectList[0]]
                local nRect = nListRect[i]
                nRectMsgData.leftTopPosX = nRect[1]
                nRectMsgData.leftTopPosY = nRect[2]
                nRectMsgData.rightBottomPosX = nRect[3]
                nRectMsgData.rightBottomPosY = nRect[4]
            end
        end
    end

    Msg.send(nSendMsg, human.fd)
end

function onFamilyWarMonsterBeHitCB(attacker, monster, monsterID, hurt, copyID, roomID, sceneID)
    local getHp = Obj.getHp
    local getHpMax = Obj.getHpMax
    local currHp = getHp(monster)
    local maxHp = getHpMax(monster)
    local hp = currHp - hurt
    local nMonsterSide = ObjMonster.getMonsterCamps(monsterID)
    if StatusList[roomID] and StatusList[roomID][nMonsterSide] and StatusList[roomID][nMonsterSide][monsterID] then
        StatusList[roomID][nMonsterSide][monsterID].BloodPre = hp / maxHp * 100
    end
end

function onSendCopyData(copyID, roomID, sceneID)
    local nSendMsg = Msg.gc.GC_FAMILYWAR_COPYDATA
    nSendMsg.occupySide = PKData[roomID].occupySide
    nSendMsg.redFlagNum = HumanWarDataList[roomID]._roomData.redScore
    nSendMsg.blueFlagNum = HumanWarDataList[roomID]._roomData.blueScore
    nSendMsg.leftTime = getLeftTime()
    nSendMsg.myKillNum = 0
    nSendMsg.monster2BloodPre = 0
    nSendMsg.monster3BloodPre = 0
    nSendMsg.blueStatusList[0] = 0
    nSendMsg.redStatusList[0] = 0

    local nFamilyUuid, nFamilyData = onGetFamilyDataBySide(roomID, BLUE_SIDE)
    nSendMsg.blueFamilyName = nFamilyData and nFamilyData.familyName or ""
    nSendMsg.blueSideZL = nFamilyData and nFamilyData.zhandouli or 0

    nFamilyUuid, nFamilyData = onGetFamilyDataBySide(roomID, RED_SIDE)
    nSendMsg.redFamilyName = nFamilyData and nFamilyData.familyName or "" 
    nSendMsg.redSideZL = nFamilyData and nFamilyData.zhandouli or 0

    if StatusList[roomID][BLUE_SIDE] then
        for k, v in pairs(StatusList[roomID][BLUE_SIDE]) do
            nSendMsg.blueStatusList[0] = nSendMsg.blueStatusList[0] + 1
            local nData = nSendMsg.blueStatusList[nSendMsg.blueStatusList[0]]
            nData.monsterID = k
            nData.count = v.count
        end
    end

    if StatusList[roomID][RED_SIDE] then
        for k, v in pairs(StatusList[roomID][RED_SIDE]) do
            nSendMsg.redStatusList[0] = nSendMsg.redStatusList[0] + 1
            local nData = nSendMsg.redStatusList[nSendMsg.redStatusList[0]]
            nData.monsterID = k
            nData.count = v.count
        end
    end

    local nFds = Obj.scenes_fds[sceneID]
    if nFds then
        for k, v in pairs(nFds) do
            if v.obj_type == Obj.TYPE_HUMAN then
                nSendMsg.myKillNum = KillList[roomID][v._id] and KillList[roomID][v._id].killcount or 0
                local nSide = onGetHumanSide(v._id)
                if nSide ~= NONE_SIDE then
                    for k, v in pairs(FamilyWarBaseConfig.monster3Data) do
                        local nMonsterSide = ObjMonster.getMonsterCamps(k)
                        if nMonsterSide == nSide and StatusList[roomID][nSide] and StatusList[roomID][nSide][k] then
                            nSendMsg.monster3BloodPre = StatusList[roomID][nSide][k].BloodPre
                        end
                    end

                end

                Msg.send(nSendMsg, k)
                --Util.printTable(nSendMsg.rankList)
            end
        end
    end
end

function onSendPKData(diffNum, humanList)
    local nSendMsg = Msg.gc.GC_FAMILYWAR_PKDATA
    nSendMsg.curLen = diffNum
    for k, v in pairs(humanList) do
        Msg.send(nSendMsg, v.fd)
    end
end

function onGetPKAreaData(mapID, copyID, roomID)
    local nCenterRedNum = 0
    local nCenterBlueNum = 0
    local nSceneID = CopyL.copyList[copyID][roomID][mapID]
    if not nSceneID or nSceneID <= 0 then
        return
    end
    local nSum, nHumanList = MapScan.scanAreaLiveHuman(mapID, nSceneID, FamilyWarBaseConfig.centerAreaID)
    if nSum > 0 then
        for nHumanUuid in pairs(nHumanList) do
            local nSide = onGetHumanSide(nHumanUuid)
            if nSide == BLUE_SIDE then
                nCenterBlueNum = nCenterBlueNum + 1
            elseif nSide == RED_SIDE then
                nCenterRedNum = nCenterRedNum + 1
            end
        end
    end
    return nCenterRedNum, nCenterBlueNum, nHumanList
end

function onPKCtl(nMapID, copyID, roomID)
    local nRedNum, nBlueNum, nHumanList = onGetPKAreaData(nMapID, copyID, roomID)
    local nDiffLen = math.ceil((nBlueNum - nRedNum) / FamilyWarBaseConfig.pkDiff)
    local nCurLen = PKData[roomID].curLen - nDiffLen
    if nCurLen < 0 then
        PKData[roomID].curLen = 0
    elseif nCurLen > FamilyWarBaseConfig.pkLen then
        PKData[roomID].curLen = FamilyWarBaseConfig.pkLen
    else
        PKData[roomID].curLen = nCurLen
    end
    local nOldOccupySide = PKData[roomID].occupySide
    if PKData[roomID].curLen >= (FamilyWarBaseConfig.pkLen - FamilyWarBaseConfig.redLen) then
        PKData[roomID].occupySide = RED_SIDE
    elseif PKData[roomID].curLen <= FamilyWarBaseConfig.blueLen then
        PKData[roomID].occupySide = BLUE_SIDE
    else
        PKData[roomID].occupySide = NONE_SIDE
    end
    return PKData[roomID].curLen, nHumanList, PKData[roomID].occupySide, nOldOccupySide
end

function onGetRandomSide()
    return (math.random(1, 100) % 2 == 0) and RED_SIDE or BLUE_SIDE
end

function onFamilyWarOneSec(copyID, roomID)
    if not HeartBeatCount[roomID] then
        return
    end

    HeartBeatCount[roomID] = HeartBeatCount[roomID] + 1

    local nCopyConfig = CopyConfig[copyID]
    local nMapID = nCopyConfig.mapList[1]

    local nCurLen, nHumanList, nNowOccupySide, nOldOccupySide = onPKCtl(nMapID, copyID, roomID)
    local nSceneID = CopyL.copyList[copyID][roomID][nMapID]
    if nNowOccupySide == NONE_SIDE and nNowOccupySide ~= nOldOccupySide then
        if nOldOccupySide == RED_SIDE then
            SceneEvent.doSceneEvent(nSceneID, 108)
        elseif nOldOccupySide == BLUE_SIDE then
            SceneEvent.doSceneEvent(nSceneID, 106)
        end
        SceneEvent.doSceneEvent(nSceneID, 103)
    elseif nNowOccupySide ~= NONE_SIDE and nNowOccupySide ~= nOldOccupySide then
        local nContent1 = nil
        local nContent2 = nil
        if nOldOccupySide == NONE_SIDE then
            SceneEvent.doSceneEvent(nSceneID, 104)
        end

        if nNowOccupySide == RED_SIDE then
            nContent1 = Lang.FAMILYWAR_PK_WINSIDE
            nContent2 = Lang.FAMILYWAR_PK_BLUESIDE_DEF
            SceneEvent.doSceneEvent(nSceneID, 106)
            SceneEvent.doSceneEvent(nSceneID, 107)
        elseif nNowOccupySide == BLUE_SIDE then
            nContent1 = Lang.FAMILYWAR_PK_WINSIDE
            nContent2 = Lang.FAMILYWAR_PK_REDSIDE_DEF
            SceneEvent.doSceneEvent(nSceneID, 108)
            SceneEvent.doSceneEvent(nSceneID, 105)
        end
        onSendSideMsg(nNowOccupySide, nContent1, roomID)
        onSendSideMsg(nNowOccupySide == RED_SIDE and BLUE_SIDE or RED_SIDE, nContent2, roomID)
    end
    onSendPKData(nCurLen, nHumanList)

    --集体复活
    if HeartBeatCount[roomID] % FamilyWarBaseConfig.humanReliveTime == 0 then
        local humanList = CopyL.getCopyHumanList(copyID, roomID)
        for k, v in pairs(humanList) do
            if v.db.hp <= 0 then
                RoleHandler.CG_REVIVE_GO_HOME(v, true)
            end
        end
    end

    if HeartBeatCount[roomID] % FamilyWarIncomeConfig.noMonster3V1[2] == 0 then
        for k, v in pairs(FamilyWarBaseConfig.monster3Data) do
            if StatusList[roomID] and StatusList[roomID][BLUE_SIDE] and StatusList[roomID][BLUE_SIDE][k] and StatusList[roomID][BLUE_SIDE][k].count > 0 then
                onDecV1(FamilyWarIncomeConfig.noMonster3V1[1], BLUE_SIDE, roomID)

            end
            if StatusList[roomID] and StatusList[roomID][RED_SIDE] and StatusList[roomID][RED_SIDE][k] and StatusList[roomID][RED_SIDE][k].count > 0 then
                onDecV1(FamilyWarIncomeConfig.noMonster3V1[1], RED_SIDE, roomID)
            end
        end
    end

    if HeartBeatCount[roomID] % FamilyWarIncomeConfig.pkAddV1[2] == 0 then
        local nOccupySide = PKData[roomID].occupySide
        onAddV1(FamilyWarIncomeConfig.pkAddV1[1], nOccupySide, roomID)
    end

    local nRemainTime = getLeftTime()
    if nRemainTime / 60 == 5 then
        onSendBroadcast(Lang.FAMILYWAR_ENDBEFORE_5MIN, Lang.UP, copyID, roomID)
    end

    --发送副本数据面板数据
    if HeartBeatCount[roomID] % 2 == 0 then
        local nSceneID = CopyL.copyList[copyID][roomID][nMapID]
        onSendCopyData(copyID, roomID, nSceneID)
    end
    
    if not Config.IS_MIDDLE then
        if FamilyWarEndTime - os.time() <= 0 then
            onFamilyWarEnd(roomID)
        end
    end
end

function onGetReviveTime(humanUuid)
    local nRoomID = CopyL.copyHuman2Room[humanUuid]
    if HeartBeatCount[nRoomID] then
        if HumanWarDataList[nRoomID].static == 1 then
            return 0
        else
            local nLeftTime = HeartBeatCount[nRoomID] % FamilyWarBaseConfig.humanReliveTime
            return FamilyWarBaseConfig.humanReliveTime - (nLeftTime == 0 and FamilyWarBaseConfig.humanReliveTime or nLeftTime)
        end
    end
end

function onJumpBackPos(human, isDead)
    local nRoomID = CopyL.copyHuman2Room[human._id]
    local nHumanWarData = HumanWarDataList[nRoomID]._humanDataList[human._id]
    if not nHumanWarData then
        return
    end
    local nSide = onGetHumanSide(human._id)
    if nSide and nSide ~= NONE_SIDE then
        if nSide == BLUE_SIDE then
            human.camps = Obj.CAMPS_GOOD
            Obj.jump(human, FamilyWarBaseConfig.blueBornPos[1], FamilyWarBaseConfig.blueBornPos[2], Msg.gc.GC_JUMP)
        elseif nSide == RED_SIDE then
            human.camps = Obj.CAMPS_BAD
            Obj.jump(human, FamilyWarBaseConfig.redBornPos[1], FamilyWarBaseConfig.redBornPos[2], Msg.gc.GC_JUMP)
        end
    end
end

--怪物死亡
function onFamilyWarMonsterDie(killer, monster, monsterID, copyID, roomID)
    local nMonster1 = false
    local nMonster2 = false
    local nMonster3 = false
    local nMonster4 = false
    local nMonster1Data = FamilyWarBaseConfig.monster1Data[monsterID]
    if nMonster1Data then
        if killer.obj_type == Obj.TYPE_HUMAN then
            nMonster1 = true
        end
    end

    local nMonster3Data = FamilyWarBaseConfig.monster3Data[monsterID]
    if nMonster3Data then
        if killer.obj_type == Obj.TYPE_HUMAN then
            nMonster3 = true
        end
    end

    local nMonster4Data = FamilyWarBaseConfig.monster4Data[monsterID]
    if nMonster4Data then
        if killer.obj_type == Obj.TYPE_HUMAN then
            nMonster4 = true
        end
    end

    local nWinSide = onGetHumanSide(killer._id)
    local nFailSide = (nWinSide == BLUE_SIDE and RED_SIDE or BLUE_SIDE)

    -- 击杀了箭塔
    if nMonster1 then
        -- 非所属方增加军备值
        onDecV1(FamilyWarIncomeConfig.killMonster1V1, nFailSide, roomID)
    end

    -- 击杀了营门
    if nMonster2 then
        onDecV1(FamilyWarIncomeConfig.killMonster2V1, nFailSide, roomID)
    end

    -- 击杀了大营
    if nMonster3 then
        onDecV1(FamilyWarIncomeConfig.killMonster3V1, nFailSide, roomID)
        local nWinContent = nil
        local nFailContent = nil
        if nWinSide == RED_SIDE then
            nWinContent = Lang.FAMILYWAR_REDSIDE_DESTORYFLAG
            nFailContent = Lang.FAMILYWAR_BLUESIDE_BEDESTORYFLAG
        elseif nWinSide == BLUE_SIDE then
            nWinContent = Lang.FAMILYWAR_BLUESIDE_DESTORYFLAG
            nFailContent = Lang.FAMILYWAR_REDSIDE_BEDESTORYFLAG
        end
        onSendSideMsg(nWinSide, nWinContent, roomID)
        onSendSideMsg(nFailSide, nFailContent, roomID)
    end

    -- 击杀了卫兵
    if nMonster4 then
        onDecV1(FamilyWarIncomeConfig.killMonster4V1, nFailSide, roomID)
    end

    local nMonsterSide = ObjMonster.getMonsterCamps(monsterID)
    if StatusList[roomID] and StatusList[roomID][nMonsterSide] and StatusList[roomID][nMonsterSide][monsterID] then
        StatusList[roomID][nMonsterSide][monsterID].count = StatusList[roomID][nMonsterSide][monsterID].count + 1 
    end
end

function onCheckComboKill()
    local nSendMsg = Msg.gc.GC_FAMILYWAR_COMBOKILL
    for nRoomID, nRoomKillData  in pairs(KillList) do
        for nHumanUuid, nKillData in pairs(nRoomKillData) do
            if nKillData.change == true then
                nKillData.change = false
                nSendMsg.killNum = nKillData.comboKillCount
                local nHuman = ObjHuman.onlineUuid[nHumanUuid]
                if nHuman then
                    Msg.send(nSendMsg, nHuman.fd)
                end
            end
        end
    end
end

--人物死亡
function onFamilyWarRoleDieCB(atker, human, copyID, roomID)
    if atker.obj_type == Obj.TYPE_MONSTER then
        local nBeKillSide = (ObjMonster.getMonsterCamps(atker.monster_id) == BLUE_SIDE and RED_SIDE or BLUE_SIDE)
        if nBeKillSide ~= NONE_SIDE then
            onDecV1(FamilyWarIncomeConfig.killHumanV1, nBeKillSide, roomID)
        end
        return
    end
    if atker.obj_type ~= Obj.TYPE_HUMAN then
        return
    end
    local nKillData = KillList[roomID][atker._id]
    if nKillData then
        local nKillDiffTime = os.time() - nKillData.comboKillTime
        if nKillDiffTime <= FamilyWarBaseConfig.comboKillTime then
            nKillData.comboKillCount = nKillData.comboKillCount + 1
        else
            nKillData.comboKillCount = 1
        end
        nKillData.killcount = nKillData.killcount + 1
        nKillData.noDieComboKillCount = nKillData.noDieComboKillCount + 1
        nKillData.comboKillTime = os.time()
        nKillData.killUuid = human._id
        nKillData.change = true
    else
        KillList[roomID][atker._id] = {comboKillTime = os.time(), killUuid = human._id, killcount = 1, comboKillCount = 1, noDieComboKillCount = 1, change = true}
        nKillData = KillList[roomID][atker._id]
    end
    --击杀增加积分
    local nKillSide = onGetHumanSide(atker._id)
    local nBeKillSide = (nKillSide == BLUE_SIDE and RED_SIDE or BLUE_SIDE)
    StatusList[roomID][nKillSide][0].count = StatusList[roomID][nKillSide][0].count + 1
    onDecV1(FamilyWarIncomeConfig.killHumanV1, nBeKillSide, roomID)

    -- 击杀广播相关
    local nContent = nil
    local nNoDieComboKillCount = nKillData.noDieComboKillCount
    local nNoDieComboKillData = FamilyWarBaseConfig.noDieComboKill[nNoDieComboKillCount]
    if (nNoDieComboKillCount - 50) % FamilyWarBaseConfig.noDieComboKillMaxNum == 0 then
        nContent = FamilyWarBaseConfig.noDieComboKill[100][1]
    else
        if nNoDieComboKillData then
            nContent = string.format(nNoDieComboKillData[1], HtmlUtil.font(atker.name, onGetSideHumanNameColor(nKillSide)), HtmlUtil.font(string.format(Lang.FAMILYWAR_COMBOKILL, nNoDieComboKillCount), "#F1FF0A"))
            onSendBroadcast(nContent, Lang.UP, copyID, roomID)
        end
    end

    local nBeKillData = KillList[roomID][human._id]
    if nBeKillData and nBeKillData.noDieComboKillCount >= FamilyWarBaseConfig.breakNoDieComboKill then
        nContent = string.format(Lang.FAMILYWAR_BREAK_COMBOKILL,
        HtmlUtil.font(atker.name, onGetSideHumanNameColor(nKillSide)),
        HtmlUtil.font(human.name, onGetSideHumanNameColor(nBeKillSide)),
        HtmlUtil.font(string.format(Lang.FAMILYWAR_COMBOKILL, nBeKillData.noDieComboKillCount), "#F1FF0A"))
        nBeKillData.noDieComboKillCount = 0
        onSendBroadcast(nContent, Lang.UP, copyID, roomID)
    end

    if HeartBeatCount[roomID] % FamilyWarBaseConfig.humanReliveTime == 0 then
        RoleHandler.CG_REVIVE_GO_HOME(human, true)
    end
end

function onFamilyWarRoomFinish(copyID, roomID)
    local nRoomHumanList = CopyL.getCopyHumanList(copyID, roomID)
    for k, v in ipairs(nRoomHumanList) do
        local nHuman = ObjHuman.onlineUuid[v._id]
        if nHuman then
            --死亡的进行最后复活
            if nHuman.db.hp <= 0 then
                RoleHandler.CG_REVIVE_GO_HOME(nHuman, true)
            end
            onHumanCtl(nHuman, roomID, copyID)
        end
    end
end

-- 清除
function onFamilyWarRoomClear(copyID, roomID)
    HumanWarDataList[roomID] = nil
    PKData[roomID] = nil
    KillList[roomID] = nil
    HeartBeatCount[roomID] = nil
    SideHumanIDList[roomID] = nil
    HeartBeatCount[roomID] = nil
    StatusList[roomID] = nil
    FamilyUuidSide[roomID] = nil
    OrderData[roomID] = nil
end

function onHumanCtl(human, roomID)
    local nSide = onGetHumanSide(human._id)
    if nSide ~= NONE_SIDE and roomID then
        HumanWarDataList[roomID]._humanDataList[human._id].status = FAMILYWAR_STATUS_LEAVED
    end

    human.camp = Obj.CAMPS_NONE
end

function onGetFamilyDataBySide(roomID, side)
    for k, v in pairs(FamilyUuidSide[roomID]) do
        if v.side == side then
            return k, v
        end
    end
    return "", nil
end

function onFamilyWarEnd(roomID)
    if HumanWarDataList[roomID] and HumanWarDataList[roomID].static == 1 then
        return
    end
    HumanWarDataList[roomID].static = 1
    local nFamilyWarRoomData = HumanWarDataList[roomID]
    if nFamilyWarRoomData then
        local nWinSide = NONE_SIDE
        if nFamilyWarRoomData._roomData.redScore > nFamilyWarRoomData._roomData.blueScore then
            nWinSide = RED_SIDE
        elseif nFamilyWarRoomData._roomData.redScore < nFamilyWarRoomData._roomData.blueScore then
            nWinSide = BLUE_SIDE
        else
            local _, nBlueSideFamilyData = onGetFamilyDataBySide(roomID, BLUE_SIDE)
            local _, nRedSideFamilyData = onGetFamilyDataBySide(roomID, RED_SIDE)
            if not nBlueSideFamilyData and nRedSideFamilyData then
                nWinSide = RED_SIDE
            elseif not nRedSideFamilyData and nBlueSideFamilyData then
                nWinSide =BLUE_SIDE
            elseif nRedSideFamilyData and nBlueSideFamilyData then
                if nBlueSideFamilyData.zhandouli > nRedSideFamilyData.zhandouli then
                    nWinSide = BLUE_SIDE
                elseif nBlueSideFamilyData.zhandouli < nRedSideFamilyData.zhandouli then
                    nWinSide = RED_SIDE
                end
            end
        end

        local nWinSideUuid = "" 
        local nFailSideUuid = "" 
        local nType = 0
        if nWinSide ~= NONE_SIDE then
            nWinSideUuid = onGetFamilyDataBySide(roomID, nWinSide)
            nFailSideUuid = onGetFamilyDataBySide(roomID, (nWinSide == BLUE_SIDE and RED_SIDE or BLUE_SIDE))
            nType = 1
        else
            nWinSideUuid = onGetFamilyDataBySide(roomID, BLUE_SIDE)
            nFailSideUuid = onGetFamilyDataBySide(roomID, RED_SIDE)
            nType = 0
        end
        local nSend2Wdata = {
            data = {roomID = roomID, type = nType, winside = nWinSideUuid, failside = nFailSideUuid}
        }
        InnerDataManagerFL.Send2WInnerData(human, InnerDataDefine.INNERDATA_TYPE_MIDDLE_FWAR_RESULT, nSend2Wdata)

        local nCopyConfig = CopyConfig[CopyDefine.COPY_FAMILYWAR_ID]
        if nCopyConfig then
            local nMapID = nCopyConfig.mapList[1]
            local nSceneID = CopyL.copyList[CopyDefine.COPY_FAMILYWAR_ID][roomID][nMapID]
            if nSceneID then
                onSendCopyData(CopyDefine.COPY_FAMILYWAR_ID, roomID, nSceneID)
            end
        end
    end

    CopyL.roomFinish(CopyDefine.COPY_FAMILYWAR_ID, roomID, CopyDefine.COPY_FINISH_ACT_END, "活动结束")
end

function onFamilyWarRoomEnd()
    for nRoomID in pairs(HumanWarDataList) do
        onFamilyWarEnd(nRoomID)
    end
end

-- 增加军备值
function onAddV1(v1, side, roomID)
    if side == RED_SIDE then
        HumanWarDataList[roomID]._roomData.redScore = HumanWarDataList[roomID]._roomData.redScore + v1
    elseif side == BLUE_SIDE then
        HumanWarDataList[roomID]._roomData.blueScore = HumanWarDataList[roomID]._roomData.blueScore + v1
    end
end

-- 扣除军备值
function onDecV1(v1, side, roomID)
    if side == RED_SIDE then
        HumanWarDataList[roomID]._roomData.redScore = HumanWarDataList[roomID]._roomData.redScore - v1
        if HumanWarDataList[roomID]._roomData.redScore <= 0 then
            onFamilyWarEnd(roomID)
        end
    elseif side == BLUE_SIDE then
        HumanWarDataList[roomID]._roomData.blueScore = HumanWarDataList[roomID]._roomData.blueScore - v1
        if HumanWarDataList[roomID]._roomData.blueScore <= 0 then
            onFamilyWarEnd(roomID)
        end
    end
end

function onBackBlood(human, moneyNum)
    local nHumanUuid = human._id
    local nCopyID = CopyL.mapID2CopyID[human.db.map_id]
    local nCurHp = ObjHuman.getHp(human)
    if not nCopyID or nCopyID <= 0 or nCurHp <= 0 then
        return
    end
    local nRoomID = CopyL.copyHuman2Room[human._id]
    local nHumanWarData = HumanWarDataList[nRoomID]._humanDataList[nHumanUuid]
    if nHumanWarData and nHumanWarData.status == FAMILYWAR_STATUS_NORMAL then
        local msgErr = Msg.gc.GC_BROADCAST
        msgErr.type = Lang.MOUSE
        local nBackBloodNum = ObjHuman.getHpMax(human) - nCurHp
        if nBackBloodNum == 0 then
            msgErr.msg = "血量已满!"
            Msg.send(msgErr, human.fd)
            return
        end
        local nHumanMoney = ObjHuman.getYinliang(human)
        if nHumanMoney < FamilyWarBaseConfig.backBloodMoney then
            msgErr.msg = "银两不足!"
            Msg.send(msgErr, human.fd)
            return
        end
        local nNeedMoney = FamilyWarBaseConfig.backBloodMoney * (math.ceil(nBackBloodNum / FamilyWarBaseConfig.backBloodPre))
        local nRealMoney = (nNeedMoney <= nHumanMoney) and nNeedMoney or nHumanMoney
        if nRealMoney > 0 then
            local nIsInSideArea = false
            local nSide = onGetHumanSide(human._id)
            if nSide == RED_SIDE then
                for k, v in pairs(FamilyWarBaseConfig.redBackBloodAreaID) do
                    if Map.is_in_area_id(human.db.map_id, human.db.x, human.db.y, v) then
                        nIsInSideArea = true
                        break
                    end
                end
            elseif nSide == BLUE_SIDE then
                for k, v in pairs(FamilyWarBaseConfig.blueBackBloodAreaID) do
                    if Map.is_in_area_id(human.db.map_id, human.db.x, human.db.y, v) then
                        nIsInSideArea = true
                        break
                    end
                end
            end
            if not nIsInSideArea then
                msgErr.msg = "请到所属方回血!"
                Msg.send(msgErr, human.fd)
                return
            end
            ObjHuman.decYinliang(human, nRealMoney, "familywarbackblood")
            local nAddHp = nRealMoney * FamilyWarBaseConfig.backBloodPre
            ObjHuman.setHp(human, nCurHp + nAddHp)
            msgErr.msg = string.format("成功回血%d!消耗%d银两", nAddHp, nRealMoney)
            Msg.send(msgErr, human.fd)
        else
            msgErr.msg = "银两不足!"
            Msg.send(msgErr, human.fd)
        end
    end

end

function onGetSideHumanNameColor(side)
    if side == RED_SIDE then
        return "#FF0000"
    elseif side == BLUE_SIDE then
        return "#00B0F0"
    end
end

function onSendBroadcast(content, type, copyID, roomID)
    local nMsg = Msg.gc.GC_BROADCAST
    nMsg.type = type
    nMsg.msg = content
    CopyL.sendCopy(nMsg, copyID, roomID)
end

function onSendSideMsg(side, content, roomID)
    local nFds = onGetSideFds(side, roomID)
    if nFds[0] > 0 then
        Broadcast.sendBroadcastFDs(nFds, Lang.UP, content)
    end
end

function onSendSideTxt(side, content, roomID)
    local mm = Msg.gc.GC_SHOW_TXT
    mm.txt = content 
    local nFds = onGetSideFds(side, roomID)
    if nFds[0] > 0 then
        mm.txt = content 
        Msg.sendMulti(mm, nFds)
    end
end

function onGetSideFds(side, roomID)
    local nFds = {}
    local nLen = 0
    for k in pairs(SideHumanIDList[roomID][side]) do
        local nHuman = ObjHuman.onlineUuid[k]
        if nHuman and nHuman.fd then
            nLen = nLen + 1
            nFds[nLen] = nHuman.fd
        end
    end
    nFds[0] = nLen
    return nFds
end

function onOrder(human, type)
    local nSide = onGetHumanSide(human._id)
    if nSide == NONE_SIDE then
        return
    end

    local nRoomID = CopyL.copyHuman2Room[human._id]
    if nRoomID and nRoomID > 0 and SideHumanIDList[nRoomID] then
        local msgErr = Msg.gc.GC_BROADCAST
        msgErr.type = Lang.MOUSE
        if Config.IS_MIDDLE then
            local __, nFamilyData = onGetFamilyDataBySide(nRoomID, nSide)
            if nFamilyData then
                if human._id ~= nFamilyData.leaderUuid and human._id ~= nFamilyData.leaderFuUuid then
                    msgErr.msg = "只能主公和军师才能点击发号!"
                    Msg.send(msgErr, human.fd)
                    return
                end
            end
        end

        if OrderData[nRoomID][human._id] and OrderData[nRoomID][human._id][type] and os.time() - OrderData[nRoomID][human._id][type] < 30 then
            msgErr.msg = "发号冷却中..."
            Msg.send(msgErr, human.fd)
            return
        end

        if not OrderData[nRoomID][human._id] then
            OrderData[nRoomID][human._id] = {[type] = os.time()}
        else
            OrderData[nRoomID][human._id][type] = os.time()
        end
        local nContent = ""
        if type == 0 then
            nContent = Lang.FAMILYWAR_ORDER_CAP
        elseif type == 1 then
            nContent = Lang.FAMILYWAR_ORDER_ATK
        elseif type == 2 then
            nContent = Lang.FAMILYWAR_ORDER_DEF
        end

        onSendSideTxt(nSide, nContent, nRoomID)
        onSendOrderData(human, nRoomID)
    end
end

function onSendOrderData(human, roomID)
    if OrderData[roomID][human._id] then
        local nSendMsg = Msg.gc.GC_FAMILYWAR_ORDER
        nSendMsg.orderList[0] = 0
        for i = 0, 2 do 
            nSendMsg.orderList[0] = nSendMsg.orderList[0] + 1
            local nOrderData = nSendMsg.orderList[nSendMsg.orderList[0]]
            nOrderData.type = i
            nOrderData.cdtime = 0
            if OrderData[roomID][human._id][i] then
                nOrderData.cdtime = 30 - (os.time() - OrderData[roomID][human._id][i])
            end
        end
        Msg.send(nSendMsg, human.fd)
    end
end

function onFamilyWarEvent(human, oType, data)
    if data.type == 1 then --开始
        local nCopyConfig = CopyConfig[CopyDefine.COPY_FAMILYWAR_ID]
        local nMapID = nCopyConfig.mapList[1]
        local logicID = Map.get_logic_id(nMapID)
        if _G.logic_id == logicID then
            print("room begin:", data.roomID)
            FamilyWarActData = data
            local roomID = data.roomID
            FamilyUuidSide[roomID] = {}
            StatusList[roomID] = {}
            local nSide = onGetRandomSide()
            local nActData = getActData()
            if not nActData then
                return
            end

            for k, v in ipairs(data.family) do
                if not FamilyUuidSide[roomID][v.familyUuid] then
                    FamilyUuidSide[roomID][v.familyUuid] = {}
                    FamilyUuidSide[roomID][v.familyUuid].side = nSide
                    FamilyUuidSide[roomID][v.familyUuid].familyName = v.familyName or ""
                    FamilyUuidSide[roomID][v.familyUuid].zhandouli = v.zhandouli or 0 
                    FamilyUuidSide[roomID][v.familyUuid].leaderUuid = v.leaderUuid or "" 
                    FamilyUuidSide[roomID][v.familyUuid].leaderFuUuid = v.leaderFuUuid or "" 
                    StatusList[roomID][nSide] = {}

                    for k, v in pairs(FamilyWarBaseConfig.monster3Data) do
                        local nMonsterSide = ObjMonster.getMonsterCamps(k) 
                        if nMonsterSide == nSide then
                            StatusList[roomID][nSide][k] = {BloodPre = 100, count = 0}
                        end
                    end
                    StatusList[roomID][nSide][0] = {count = 0}
                    nSide = (nSide == RED_SIDE and BLUE_SIDE or RED_SIDE)
                end
            end

            HumanWarDataList[roomID] = {}
            HumanWarDataList[roomID]._roomData = {redScore = FamilyWarBaseConfig.redV1, blueScore = FamilyWarBaseConfig.blueV1}
            HumanWarDataList[roomID]._humanDataList = {}
            --HumanWarDataList[roomID].static = -1    -- -1 备战状态 0 战斗状态 1 结束状态

            SideHumanIDList[roomID] = {}
            SideHumanIDList[roomID][RED_SIDE] = {}
            SideHumanIDList[roomID][BLUE_SIDE] = {}

            PKData[roomID] = {curLen = FamilyWarBaseConfig.pkLen / 2, occupySide = 0}
            KillList[roomID] = {}
            OrderData[roomID] = {}
            HeartBeatCount[roomID] = 0

        end
    else  --结束时，结束所有房间
        onFamilyWarRoomEnd() 
    end
end

InnerDataManagerFL.Register(InnerDataDefine.INNERDATA_TYPE_MIDDLE_FAMILY_WAR, onFamilyWarEvent)
